package com.jky.filesystem.slice;

import com.jky.filesystem.ResourceTable;
import com.jky.filesystem.devices.SelectDeviceDialog;
import com.jky.filesystem.utils.FileUtils;
import com.jky.filesystem.utils.ToastDialogUtils;
import com.lxj.xpopup.XPopup;
import ohos.aafwk.ability.*;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.IntentParams;
import ohos.aafwk.content.Operation;
import ohos.data.resultset.ResultSet;
import ohos.distributedschedule.interwork.DeviceInfo;
import ohos.distributedschedule.interwork.DeviceManager;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.photokit.metadata.AVStorage;
import ohos.system.version.SystemVersion;
import ohos.utils.net.Uri;
import ohos.utils.zson.ZSONObject;

import java.io.*;
import java.nio.channels.FileChannel;
import java.util.*;

public class RemoteAbilitySlice extends AbilitySlice implements IAbilityContinuation {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, "测试");

    private Boolean isRemote = false;

    private final Integer apiVersion = SystemVersion.getApiVersion();   //获取当前API版本，2.2之后调试机的版本升级成6了，5暂时没用了

    private final int SelectFileCode=1123;

    private String fileType = null;

    @Override
    public void onStart(Intent intent) {
        HiLog.info(LABEL_LOG,"onStart");
        super.onStart(intent);

        HiLog.info(LABEL_LOG,"当前设备API版本：" + apiVersion);

        if(apiVersion == 6) {
            super.setUIContent(ResourceTable.Layout_ability_remote);
            initComponentsAPI6();
        }
        else if(apiVersion < 6) {
            super.setUIContent(ResourceTable.Layout_ability_remote_SDK5);
            initComponentsAPI5();
        }
        if(isRemote) {
            initShareDialog();
        }
        else {
            createFile();
        }
    }

    private void createFile() {
        String filePath = getExternalFilesDir("out") + File.separator + "hello.txt";
        FileWriter fileWriter;
        try {
            fileWriter = new FileWriter(filePath, true);
            fileWriter.write("Hello World");
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //初始化按钮，绑定事件（API6）
    private void initComponentsAPI6() {
        findComponentById(ResourceTable.Id_selectFile).setClickedListener(component -> selectFile("*/*"));
        findComponentById(ResourceTable.Id_showRemoteList).setClickedListener(component -> showDistributedList());
    }

    //初始化按钮，绑定事件（API5）
    private void initComponentsAPI5() {
        findComponentById(ResourceTable.Id_selectPic).setClickedListener(component -> selectFile("image/*"));
        findComponentById(ResourceTable.Id_selectVideo).setClickedListener(component -> selectFile("video/*"));
        findComponentById(ResourceTable.Id_selectAudio).setClickedListener(component -> selectFile("audio/*"));
    }

    //调用android的api选择文件
    private void selectFile(String type) {
        Intent intent = new Intent();
        //"android.intent.action.GET_CONTENT" 或 "android.intent.action.PICK"调起android 选择文件 api
        Set<String> entities = new HashSet<>();
//        entities.add("android.intent.category.APP_CALCULATOR");
        Operation opt = new Intent.OperationBuilder()
                .withAction("android.intent.action.GET_CONTENT")
//                .withEntities(entities)
                .build();
        intent.setOperation(opt);
        intent.addFlags(Intent.FLAG_NOT_OHOS_COMPONENT);
        intent.setType(type);   //用这个可以只选择文件，但是要从“文件”和“文件管理器”中选择
        fileType = type;
        startAbilityForResult(intent, SelectFileCode);
    }

    //启动分布式
    private void countAbility() {
        HiLog.info(LABEL_LOG,"点击分享按钮");

        List<DeviceInfo> onlineDevices = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ALL_DEVICE);
        showDevicesDialog(onlineDevices);
    }

    //展示选择设备列表
    private void showDevicesDialog(List<DeviceInfo> devices) {
        new SelectDeviceDialog(this, devices, deviceInfo -> continueAbility(deviceInfo.getDeviceId())).show();
    }

    //查看分布式目录下面有多少文件
    private void showDistributedList() {
        HiLog.info(LABEL_LOG,"点击展示按钮");
        File dir = new File(getDistributedDir().toString());
        if(dir.exists()) {
            File[] files = dir.listFiles();
            HiLog.info(LABEL_LOG,"分布式文件目录下有" + files.length + "个文件");
            for (File file : files) {
                HiLog.info(LABEL_LOG,"文件Name：" + file.getName());
                HiLog.info(LABEL_LOG,"文件Path：" + file.getPath());
            }

        }
        HiLog.info(LABEL_LOG,"展示按钮执行完毕");
    }

    //选择文件后的处理
    @Override
    protected void onAbilityResult(int requestCode, int resultCode, Intent resultData) {
        HiLog.info(LABEL_LOG, "onAbilityResult");
        HiLog.info(LABEL_LOG, "类型：" + resultData.getType());
        HiLog.info(LABEL_LOG, "选择的uri为：" + resultData.getUri());

        if (requestCode == SelectFileCode && resultData != null) {
            if (getDistributedDir() == null) {
                ToastDialogUtils.showDialog(this, "分布式文件夹异常！");
                return;
            }
            if(apiVersion == 6) {
                //SDK6版本可以直接获取到dataability格式的uri，并能直接读取
                if(FileUtils.CopyFileToDirByUri(resultData.getUri(),getDistributedDir().toString(),this)) {
                    ToastDialogUtils.showDialog(this,"复制成功!");
                    countAbility();
                }
                else {
                    ToastDialogUtils.showDialog(this,"复制失败!");
                }
            }
            else if(apiVersion < 6){
                //判断文件类型
                Uri encodeUri;
                String[] projections;
                String ID;
                String DATA;
                switch (fileType) {
                    case "image/*": {
                        projections =
                                new String[] {
                                        AVStorage.Images.Media.ID,
                                        AVStorage.Images.Media.DISPLAY_NAME,
                                        AVStorage.Images.Media.DATA,
                                        AVStorage.Images.Media.MIME_TYPE
                                };
                        encodeUri = AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI;
                        ID = AVStorage.Images.Media.ID;
                        DATA = AVStorage.Images.Media.DATA;
                        break;
                    }
                    case "audio/*": {
                        projections =
                                new String[] {
                                        AVStorage.Audio.Media.ID,
                                        AVStorage.Audio.Media.DISPLAY_NAME,
                                        AVStorage.Audio.Media.DATA,
                                        AVStorage.Audio.Media.MIME_TYPE
                                };
                        encodeUri = AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI;
                        ID = AVStorage.Audio.Media.ID;
                        DATA = AVStorage.Images.Media.DATA;
                        break;
                    }
                    case "video/*": {
                        projections =
                                new String[] {
                                        AVStorage.Video.Media.ID,
                                        AVStorage.Video.Media.DISPLAY_NAME,
                                        AVStorage.Video.Media.DATA,
                                        AVStorage.Video.Media.MIME_TYPE
                                };
                        encodeUri = AVStorage.Video.Media.EXTERNAL_DATA_ABILITY_URI;
                        ID = AVStorage.Video.Media.ID;
                        DATA = AVStorage.Images.Media.DATA;
                        break;
                    }
                    default:
                        projections =
                                new String[] {
                                        AVStorage.Downloads.ID,
                                        AVStorage.Downloads.DISPLAY_NAME,
                                        AVStorage.Downloads.DATA,
                                        AVStorage.Downloads.MIME_TYPE
                                };
                        encodeUri = AVStorage.Downloads.EXTERNAL_DATA_ABILITY_URI;
                        ID = AVStorage.Downloads.ID;
                        DATA = AVStorage.Images.Media.DATA;
                        break;
                }


                DataAbilityHelper helper = DataAbilityHelper.creator(this);
                InputStream in = null;
                OutputStream out = null;
//                FileDescriptor fileDescriptor = databaseHelper.openFile(
//                        Uri.parse("dataability:///ohos.samples.userdata/document?userdataability.txt"), "r");

                Uri uri = Uri.appendEncodedPathToUri(encodeUri, resultData.getUri().getLastPath());
                HiLog.info(LABEL_LOG, uri.toString());
                try {
                    ResultSet results = helper.query(uri, projections, null);
                    while (results != null && results.goToNextRow()) {
                        int mediaId = results.getInt(results.getColumnIndexForName(ID));
                        String fullFileName = results.getString(results.getColumnIndexForName(DATA));
                        String fileName = fullFileName.substring(fullFileName.lastIndexOf(File.separator) + 1);
                        Uri contentUri = Uri.appendEncodedPathToUri(encodeUri, "" + mediaId);
                        FileDescriptor fileDescriptor = helper.openFile(contentUri, "r");
                        String distributedFilePath = getContext().getDistributedDir().getPath() + File.separator + fileName;
                        File fr = new File(distributedFilePath);
                        in = new FileInputStream(fileDescriptor);
                        out = new FileOutputStream(fr);
                        byte[] buffers = new byte[1024*256];
                        int count;
                        while ((count = in.read(buffers)) != -1) {
                            out.write(buffers, 0, count);
                        }
                        out.close();
                        File[] files = new File(getDistributedDir().toString()).listFiles();
                        HiLog.info(LABEL_LOG,"当前分布式文件数量：" + files.length);
                        countAbility();
                    }
                } catch (DataAbilityRemoteException | IOException e) {
                    e.printStackTrace();
                    HiLog.error(LABEL_LOG,"复制到分布式文件夹出错：" + e.getMessage());
                }
                finally {
                    try {
                        if (in != null) {
                            in.close();
                        }
                        if (out != null) {
                            out.close();
                        }
                    } catch (IOException e) {
//                        LogUtil.error(TAG, "io exception");
                        HiLog.error(LABEL_LOG,"关闭文件流出错：" + e.getMessage());
                    }
                }
            }
        }
        else {
            ToastDialogUtils.showDialog(this,"请选择正确文件类型！");
        }

    }

    //分享文件按钮，弹出弹窗，确定后将文件复制到自定义的项目目录下
    private void initShareDialog() {
        HiLog.info(LABEL_LOG,"进入initShareDialog");
        new XPopup.Builder(getContext()).asConfirm("检测到文件分享", "是否接受文件",
                () -> {
                    HiLog.info(LABEL_LOG, "点击了确定");
                    //将分布式文件夹下的文件复制到指定目录下
                    File[] disFiles = new File(getDistributedDir().toString()).listFiles();
                    HiLog.info(LABEL_LOG,"文件数量：" + disFiles.length);
                    for (File file : disFiles) {
                        HiLog.info(LABEL_LOG, "复制的文件名：" + file.getPath());
                        if(FileUtils.CopyFileToDirByFile(file, getExternalFilesDir("Distributed").toString())){
                            boolean deleteSuccess = file.delete();
                            HiLog.info(LABEL_LOG,"删除结果：" + deleteSuccess);
                        }
                    }
                    ToastDialogUtils.showDialog(this,"传输完毕");
                })
                .setCancelText("取消").setConfirmText("确定").show();
    }


    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }


    @Override
    public boolean onStartContinuation() {
        HiLog.info(LABEL_LOG,"开始迁移");
        return true;
    }

    @Override
    public boolean onSaveData(IntentParams intentParams) {
        HiLog.info(LABEL_LOG,"开始保存数据");
        return true;
    }

    //分布式被启动
    @Override
    public boolean onRestoreData(IntentParams intentParams) {
        HiLog.info(LABEL_LOG,"onRestoreData");
        isRemote = true;
        return true;
    }

    @Override
    public void onCompleteContinuation(int i) {
        HiLog.info(LABEL_LOG,"迁移完成");
    }
}
